//#ifdef a
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
//构造（Construct）
void Teststring1() {
	string s1;//空构造--default -->string()
	string s2("hello", 3);//from buffer ->string(const char* s, size_t n);
	string s3("hello");//string (const char* s)	;
	string s4(s3);//copy -->string(const string & str);
	string s5(10, 'a');//fill-->string(size_t n, char c);

	cin >> s1;
	cout << "s1:" << s1 << endl;
	cout << "s2:" << s2 << endl;
	cout << "s3:" << s3 << endl;
	cout << "s4:" << s4 << endl;
	cout << "s5:" << s5 << endl;
	//可覆盖
	cin >> s2;
	cout << "s2:" << s2 << endl;
}

//容量（Capacity）
void Teststring2() {
	string s("Hello");
	cout << "size : " << s.size() << endl;
	cout << "capacity : " << s.capacity() << endl;
	cout << "length : " << s.length() << endl;
	if (!s.empty())
		cout << "不是空字符串" << endl;
	s.clear();
	if (s.empty())
		cout << "是空字符串" << endl;
	cout << endl << "reserve Test" << endl;
	//reserve 扩容
	s.reserve(20);//扩到20
	cout << "size : " << s.size() << endl;
	cout << "capacity : " << s.capacity() << endl;

	s.reserve(20);//缩小到20--》不进行次操作
	cout << "size : " << s.size() << endl;
	cout << "capacity : " << s.capacity() << endl;

	s.reserve(10);//缩小到10--》成功
	cout << "size : " << s.size() << endl;
	cout << "capacity : " << s.capacity() << endl;

	//当newcapacity > oldcapacity时，才会真正进行扩容操作
	//	当newcapacity < oldcapacity
	//	Newcapacity >= 16, 不会缩小
	//	Newcapacity <= 15, 空间缩小
}

void Teststring3() {
	string s("hello");
	/*
		char*
		size _t size
		size_t capacity
	*/
	//动态类型顺序表应该是12个字节
	cout << "sizeof : " << sizeof(s) << endl;//28
	//28个字节--》12 + 16
	// vs中使用PJ版本STL，内部维护了一个固定大小的数组，数组空间为16个字节（包括一个字节的'\0 '）
	//目的是为了提高效率，不用每次都重新申请空间 

}
void Teststring4() {
	//容量：固定维护一个15字节大小的数组空间，包不包括'\0'
	string s("123456789123456");//15	
	cout << "sizeof : " << sizeof(s) << endl;//28
	cout << "capacity : " << s.capacity() << endl;//15
	string s1("123456789123456");//16
	cout << "sizeof : " << sizeof(s1) << endl;//28
	cout << "capacity : " << s1.capacity() << endl;//31
	cout << s[15] << endl;//自动添加'\0'
	cout << '\0' << endl;//'\0'打印显示为空
	//结论： capacity不包括'\0 '
}
void Teststring5() {
	//resize
	//void resize(size_t newsize, char ch)//多出空间以‘ch’填充
	//void resize(size_t newsize)//多出空间以‘\0’填充
	//将有效字符个数修改到newsize，增多过程中可能会产生扩容
	string s("hello");
	s.resize(10);
	//使用resize可能会扩容，但不会缩小容量
}
void Teststring6() {
	//查看扩容
	string s;//不能写()
	size_t cap = s.capacity();
	for (size_t i = 0; i < 100; i++) {
		s.push_back('a');//插入
		if (cap != s.capacity()) {
			cap = s.capacity();
			cout << cap << endl;
		}
	}
	//结论：每次扩容到原来的1.5倍
	//变插入边扩容，效率较低，可使用reserve

}

//元素访问（Electment assess）
void Teststring7() {
	string s("qwqaa");
	s[4] = 'A';
	cout << s[4] << endl;
	s[4] = 'a';
	cout << s.at(4) << endl;
	//[] 和 at的区别-》越界处理不同
	//[]-->断点处理
	//at-->抛异常
}

//修改（Modifiers）
void Teststring8() {
	//operator += 
	cout << "operator +=" << endl;
	string s1("hello");
	string s(" good job!");
	s1 += ' ';//char
	s1 += "bit";//char*
	s1 += s;//string
	cout << s1 << endl;

	//append
	cout << endl << "append : " << endl;
	string s2("hello");
	//operator += 
	s2.append(1, ' ');//append (size_t n, char c);
	s2.append("bit");//char*
	s2.append(s);//string
	s2.append(" 123456789", 5);//char* s, size_t n; 前n个字符
	s2.append("abcdefgh", 1, 6);//区间追加
	cout << s2 << endl;
	
	//push_back
	cout << endl << "push_back : " << endl;
	//void push_back(char c)-->尾插
	string s3("hello");
	s3.push_back(' ');
	s3.push_back('b');
	s3.push_back('i');
	s3.push_back('t');
	cout << s3 << endl;
	
	//assign
	//assign方法可以理解为先将原字符串清空，然后赋予新的值作替换。
	cout << endl << "assign : " << endl;
	string s4("hello");
	s4.assign(s);
	cout << s4 << endl;
}
void Teststring9() {
	std::string str = "to be question";
	std::string str2 = "the ";
	std::string str3 = "or not to be";

	str.insert(6, str2);                 // to be (the )question
	str.insert(6, str3, 3, 4);             // to be (not )the question
	str.insert(10, "that is cool", 8);    // to be not (that is )the question
	str.insert(10, "to be ");            // to be not (to be )that is the question
	str.insert(15, 1, ':');               // to be not to be(:) that is the question
	str.insert(str.begin() + 5, ','); // to be(,) not to be: that is the question
	str.insert(str.end(), 3, '.');       // to be, not to be: that is the question(...)

}
void Teststring10() {
	string s(" hello bit!");
	cout << s << endl;
	s.erase(s.find(' ',0),1);//删除具体位置
	cout << s << endl;
	s.erase(0, 5);//从0开始删除4个字符
	cout << s << endl;
	//s.erase(5, 8);//删除区间
}

//迭代器(iterator)
void Teststring11() {
	//遍历
	string s("hello bit!");
	for (size_t i = 0; i < s.size(); i++)
		cout << s[i] << ' ';
	cout << endl;

	for (auto e : s)
		cout << e << ' ';
	cout << endl;

	for (string::iterator is = s.begin(); is < s.end(); is++) {
		cout << *is << ' ';
	}
	//正向迭代器iterator 是 std::string类的内部成员
	cout << endl;

	
	auto temp = s.rend();//
	//cout << *temp << endl;
	auto ris = s.rbegin();
	for (; ris < s.rend(); ris++)
		cout << *ris << ' ';
	cout << endl;
	
	//string::reverse_iterator rit = s.rbegin();
	//while (rit != s.rend()){
	//	cout << *rit << ' ';
	//	rit++;
	//}
	cout << endl;
	///反向迭代器reverse_iterator是 std::string类的内部成员
	//begin指向第一个元素，end指向最后一个元素的下一个位置 
	//rbegin指向最后一个元素,rend指向第一个元素前面的位置
	//begin和rbegin所指的元素均不包括'\0',如"abcd"第一个元素是a，最后一个元素是d，最后一个元素的下一个位置才是'\0'
	//且对于反向迭代器来说，++相当于正向迭代器的--；
}

void Teststring12(){
	//逆置函数reverse，利用了迭代器
	string s("abcdefg");
	cout << s << endl;
	reverse(s.begin(), s.end());
	cout << s << endl;
	reverse(s.rbegin(), s.rend());
	cout << s << endl;
}
//string类与输入输出
void Teststring13() {
	//逐个单词
	string s1;
	while (cin >> s1)//ctrl + z结束程序
		cout <<s1.size() <<endl;

	//逐行
	string s2;
	while (getline(cin, s2))//ctrl + z结束程序
		cout << s2 << endl;
}

//string类的关系运算
void Teststring14() {
	string s1("abcde");
	string s2("Wasodij");
	if (s1 > s2)
		cout << "s1 > s2" << endl;
	//与c语言字符串比较相同  
	
	//字符串排序
	string ss[] = { "aa","asdas","fsa","tdfs" };
	//sort(ss, ss + sizeof(ss)/ sizeof(string));
	sort(ss->begin(), ss->end());
	size_t i = 4;
	//字符串数组-》每一个元素都是一个string	
	cout << *(ss + 1)<< endl;//数组名仍是首元素地址...
	
	while (i) {
		i--;
		cout << ss[i] << endl;
	}
}
//获取一个文件的后缀
void TeststringFile() {
	string filename("abcd.asd.txt");
	cout << filename.substr(filename.rfind('.') + 1) << endl;

	//// 获取file的后缀
	//string file1("string.cpp");
	//size_t pos = file1.rfind('.');
	//cout << pos << endl;
	//cout << file1.size() << endl;
	////string suffix(file1.substr(pos, file1.size() - pos));
	//string suffix(file1.substr(pos));
	//cout << suffix << endl;
}

//一行单词，单词和单词之间使用空格隔开，最后一个单词的长度
void TeststringWordsLength() {
	string words;
	while(getline(cin, words))
	//getline:单行输入，遇到空格不停止，头文件<string>
		cout << words.substr(words.rfind(' ') + 1).size() << endl;
}

//取出域名
//删除url的协议前缀
void TeststringDomin(){
	string url("http://www.cplusplus.com/reference/string/string/find/");
	//取出域名
	size_t start = url.find("://");
	if (start == string::npos){
		cout << "域名不存在!" << endl;
		return;
	}
	start += 3;
	size_t end = url.find('/', start);
	cout << url.substr(start, end - start) << endl;
	
	//删除url的协议前缀
	size_t length = url.find("://");
	url.erase(0, length);
	cout << url << endl;
}
int main(){
	Teststring14();
	return 0;
}


//#endif